package com.samsungmobile.common.email;

import dnsclient.*;
import dnsclient.record.*;

import java.io.*;
import java.util.*;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Enumeration;
import javax.mail.internet.AddressException;

import com.samsungmobile.common.Logger;

/**
 * �̸��� �˻� Ŭ����
 * (������, /�� �˻�)
 * @author msjung
 *
 */
public class EmailCheck {

  private String strDNSServer = "193.101.111.10";
  private String strFromEmail = "";
  private String strFromDomainName = "";
  private Vector vcDNSServer = null;

  /**
   * ����
   */
  public EmailCheck() {
    try {
      InputStream in = new FileInputStream("/etc/resolv.conf");
      EmailProperties p = new EmailProperties();
      p.load(in);
      in.close();
      strDNSServer = p.getProperty("nameserver", "193.101.111.10");
      vcDNSServer = p.getProperties();
    }
    catch (Exception e) {
    	Logger.printError(e);
    }
  }


  
 
  
  
  /**
   * ����
   * @param strDNSServer String
   */
  public EmailCheck(String strDNSServer) {
    this.strDNSServer = strDNSServer;
  }

  /**
   * ����
   * @param strDNSServer String
   * @param strFromEmail String
   * @param strFromDomainName String
   */
  public EmailCheck(String strDNSServer, String strFromEmail,
                    String strFromDomainName) {
    this.strDNSServer = strDNSServer;
    this.strFromEmail = strFromEmail;
    this.strFromDomainName = strFromDomainName;
  }

  /**
   * javamail; �̿� email������ �´��� üũ �Լ�
   * @param strEmail String
   * @throws AddressException
   */
  public void ValidateMail(String strEmail) throws javax.mail.internet.
      AddressException {
    javax.mail.internet.InternetAddress iadd = new javax.mail.internet.
        InternetAddress(strEmail);
    iadd.validate();
  }

  /**
   * ���ϼ��� x�翩�� üũ �Լ�
   * @param strToEmail String
   * @return boolean
   */
  public boolean CheckEmailServer(String strToEmail) {
    try {
      ValidateMail(strToEmail);
      String strDomain = strToEmail.substring(strToEmail.indexOf("@") + 1,
                                              strToEmail.length());
	  checkDomainName(strDomain);
      if (vcDNSServer != null) {
        for (int i = 0; i < vcDNSServer.size(); i++) {
          String strTmpDNSServer = (String) vcDNSServer.elementAt(i);
          try{
            ArrayList arrlist = MXRecords(strDomain, strTmpDNSServer);
            if (arrlist.size() != 0) {
              return true;
            }
          }
          catch (UnknownNameException unex) {
            // �˼��� ������ �̸��� ��� Exception
        	  Logger.printError(unex);
        	  return false;
          }
          catch (Exception e) {
        	  Logger.printError(e);
        	  return false;
          }
        }
      }
    }
    catch (Exception x) {
    	Logger.printError(x);
    }
    return false;
  }

  /**
   * ���ϼ��� �ùٸ� ����� ���θ� üũ �Լ�
   * @param strToEmail String
   * @return boolean
   */
  public boolean CheckEmailUser(String strToEmail) {
    try {
      ValidateMail(strToEmail);
      String strDomain = strToEmail.substring(strToEmail.indexOf("@") + 1,
                                              strToEmail.length());
      checkDomainName(strDomain);
      ArrayList arrlist = MXRecords(strDomain);
      if (arrlist.size() != 0) {
        for (int count = 0; count < arrlist.size(); count++) {
          debug(arrlist.get(count).toString());
          if (ValidateUser(arrlist.get(count).toString(), strToEmail)) {
            return true;
          }
        }
      }
    }
    catch (Exception x) {
    	Logger.printError(x);
    }
    return false;
  }

  /**
   * ���ϼ��� dȮ�� ����ڿ��θ� Ȯ�� �ϴ� �Լ�
   * @param strMailServer String
   * @param strToMail String
   * @throws Exception
   * @return boolean
   */
  private boolean ValidateUser(String strMailServer, String strToMail) throws
      Exception {
    DNSQuery query = new DNSQuery(strMailServer, DNS.TYPE_A,
                                  DNS.CLASS_IN);
    Socket socket = new Socket(strDNSServer, DNS.DEFAULT_PORT);
    socket.setSoTimeout(3000);
    sendQuery(query, socket);
    getResponse(query, socket);
    socket.close();

    Enumeration eaddr = query.getAnswers();
    InetAddress ipaddr = null;
    while (eaddr.hasMoreElements()) {
      try {
        Address SMTPServerAddress = (Address) eaddr.nextElement();
        ipaddr = SMTPServerAddress.getInetAddress();
        debug("ipaddr", "" + ipaddr);
        Socket socketIP = new Socket(ipaddr, 25);
        socketIP.setSoTimeout(3000);
        PrintStream printOut = new PrintStream(socketIP.
                                               getOutputStream());
        BufferedReader rederIn = new BufferedReader(new
            InputStreamReader(socketIP.getInputStream()));
        String m_rline;
        try {
          while ( (m_rline = rederIn.readLine()) != null) {
            debug(m_rline);
          }
        }
        catch (Exception e) {
        }
        printOut.print("HELO " + strFromDomainName + "\r\n");
        printOut.flush();
        String strReadLine1 = rederIn.readLine();
        debug(strReadLine1);
        if (!strReadLine1.startsWith("250")) {
          socketIP.close();
        }
        printOut.print("MAIL FROM:" + "<" + strFromEmail + "> " +
                       "\r\n");
        String strReadLine2 = rederIn.readLine();
        debug(strReadLine2);
        if (!strReadLine2.startsWith("250")) {
          socketIP.close();
        }
        printOut.print("RCPT TO:<" + strToMail + "> \r\n");
        String strReadLine3 = rederIn.readLine();
        debug(strReadLine3);
        if (!strReadLine3.startsWith("250")) {
          socketIP.close();
        }
        else {
          socketIP.close();
          return true;
        }
      }
      catch (Exception x) {
    	  Logger.printError(x);
      }
    }

    return false;
  }

  /**
   * ���ϼ����; arraylist�� ��n�4� �Լ�
   * @param strHostName String
   * @throws Exception
   * @return ArrayList
   */
  private ArrayList MXRecords(String strHostName) throws Exception {
    DNSQuery query = new DNSQuery(strHostName, DNS.TYPE_MX, DNS.CLASS_IN);
    Socket socket = new Socket(strDNSServer, DNS.DEFAULT_PORT);
    socket.setSoTimeout(3000);
    sendQuery(query, socket);
    getResponse(query, socket);
    socket.close();
    return getMXAddresses(query);
  }

  /**
   * ���ϼ����; arraylist�� ��n�4� �Լ�
   * @param strHostName String
   * @param strDNSServer String
   * @throws Exception
   * @return ArrayList
   */
  private ArrayList MXRecords(String strHostName, String strDNSServer) throws Exception {
    DNSQuery query = new DNSQuery(strHostName, DNS.TYPE_MX, DNS.CLASS_IN);
    Socket socket = new Socket(strDNSServer, DNS.DEFAULT_PORT);
    socket.setSoTimeout(3000);
    sendQuery(query, socket);
    getResponse(query, socket);
    socket.close();
    return getMXAddresses(query);
  }

  /**
   * DNSServer�� ���� �Լ�
   * @param query DNSQuery
   * @param socket Socket
   * @throws IOException
   */
  private void sendQuery(DNSQuery query, Socket socket) throws IOException {
    BufferedOutputStream bufferedOut =
        new BufferedOutputStream(socket.getOutputStream());
    DataOutputStream dataOut = new DataOutputStream(bufferedOut);
    byte[] data = query.extractQuery();
    dataOut.writeShort(data.length);
    dataOut.write(data);
    dataOut.flush();
  }

  /**
   * DNSServer�� ���� ��� �޴� �Լ�
   * @param query DNSQuery
   * @param socket Socket
   * @throws IOException
   */
  private void getResponse(DNSQuery query, Socket socket) throws IOException, UnknownNameException {
    InputStream bufferedIn =
        new BufferedInputStream(socket.getInputStream());
    DataInputStream dataIn = new DataInputStream(bufferedIn);
    int responseLength = dataIn.readUnsignedShort();
    byte[] data = new byte[responseLength];
    dataIn.readFully(data);
    query.receiveResponse(data, responseLength);
  }

  /**
   * ���ϼ����; arrlist�� ��� �Լ�
   * @param query DNSQuery
   * @return ArrayList
   */
  private ArrayList getMXAddresses(DNSQuery query) {
    Enumeration eanswer = query.getAnswers();
    ArrayList arrlist = new ArrayList();
    while (eanswer.hasMoreElements()) {
      MailExchanger mexchanger = (MailExchanger) eanswer.nextElement();
      String strAddr = mexchanger.getMX().toString();
      arrlist.add(strAddr);
    }
    return arrlist;
  }

  /**
   * ���� �Լ�
   * @param strTitle String
   * @param strMessage String
   */
  private void debug(String strTitle, String strMessage) {
    if (false) {
    	Logger.LOG_NOHUP.error(strTitle + ":" + strMessage);
    }
  }

  /**
   * ���� �Լ�
   * @param strMessage String
   */
  private void debug(String strMessage) {
    debug("", strMessage);
  }

  /**
   * ������ �̸� �˻�. 050103 �߰�
   * @param strDomain String
   * @throws Exception
   */
  private void checkDomainName(String strDomain) throws Exception {
    boolean bRe = false;
    debug("DomainName", strDomain);
    if (strDomain == null || strDomain.startsWith(".") ||
        strDomain.endsWith(".")) {
      bRe = true;
    }
    else {
      int iIn = strDomain.indexOf(".");
      while (iIn != -1) {
        if (strDomain.charAt(iIn + 1) == '.') {
          bRe = true;
          break;
        }
        iIn = strDomain.indexOf(".", iIn + 1);
      }
    }
    if (bRe) {
      throw new Exception("Domain name ERROR");
    }
  }

}

